home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Programmer Power Tools
/
Programmer Power Tools.iso
/
tiff
/
tiff.c
< prev
next >
Wrap
C/C++ Source or Header
|
1988-11-02
|
24KB
|
904 lines
/* tiff.c - routines that parse tiff files
*
* Created 88-10-31, out of rev 3.8.
*/
#include "aldtypes.h"
#include "aldmem.h"
#include "aldutils.h"
#include "imtypes.h"
#include "swap.h"
#include "immem.h"
#include "vio.h"
#include "imag.h"
#include "imtiff.h"
#include "tiff.h"
#include "ImErr.h"
#include "ImErr2.h" /* application-dependent! for WarningAlert proto and IA_PLACE_IMAGE */
#include "tiffrout.h"
extern char *ErrorMessages;
#define min(x,y) (((y)<(x)) ? (y) : (x))
#define MAXBYTE 255
/************************ mostly local procedures *************************/
/* get data -- handles file/table and byte-order problems
* 64K max
*/
RC GtData (pDloc, order, pos, n, dtype, lpData)
PDLOC pDloc; /* data location - open file or locked-down table */
WORD order; /* byte order -- INTELTIFF or MOTOROLATIFF */
DWORD pos; /* file/table position, with respect to its beginning */
WORD n; /* number of data elements to read */
WORD dtype; /* data type: TIFFSHORT, etc */
LPSTR lpData; /* where to put the data */
{
RC err;
WORD tsize;
WORD BytesToRead;
if (n == 0)
goto done;
/* read the data
*/
if (err = GtTiffSizeof (dtype, &tsize)) {
DBMSG(("GtData: bad dtype\n"));
return err;
}
BytesToRead = tsize * n;
if (err = VRead (pDloc, pos, BytesToRead, lpData)) {
DBMSG(("GtData: VRead\n"));
DBMSG((" err=%u pos=%lu BytesToRead=%u\n",
err,pos,BytesToRead));
return err;
}
/* change the byte order, if necessary
*/
if (order != MOTOROLATIFF && order != INTELTIFF) {
DBMSG(("GtData: bad byte order: %u\n", order));
return IM_BUG; /* should have been caught earlier */
}
#ifdef WINDOWS
if (order == MOTOROLATIFF) {
#endif
#ifdef MACINTOSH
if (order == INTELTIFF) {
#endif
if (dtype == TIFFSHORT)
swab (lpData, lpData, BytesToRead);
else if (dtype == TIFFLONG)
swaw (lpData, lpData, BytesToRead);
else if (dtype == TIFFRATIONAL)
swaw (lpData, lpData, BytesToRead);
else if (dtype == TIFFSIGNED)
swab (lpData, lpData, BytesToRead);
}
/* return
*/
done: return SUCCESS;
}
#define CHUNKSIZE 32768L
/* get a possibly >64K chunk of data, by calling GtData repeatedly
*/
RC GtHugeData (pDloc, order, pos, dwN, dtype, lpData)
PDLOC pDloc; /* data location - open file or locked-down table */
WORD order; /* INTELTIFF or MOTOROLATIFF */
DWORD pos; /* file/table position, with respect to its beginning */
DWORD dwN; /* number of data elements to read */
WORD dtype; /* data type: TIFFSHORT, etc */
LPSTR lpData; /* where to put the data */
{
RC err = SUCCESS;
WORD tsize;
DWORD ElementsLeft;
DWORD ElementsToRead;
LPSTR lpOut = lpData;
DWORD ElementsPerChunk;
/* DBMSG(("GtHugeData: top\n")); */
/* get size of elements
*/
if (err = GtTiffSizeof (dtype, &tsize)) {
DBMSG(("GtHugeData: bad dtype\n"));
return err;
}
/* calculate number of elements per chunk
*/
ElementsPerChunk = CHUNKSIZE / tsize;
/* DBMSG((" ElementsPerChunk=%lu\n",ElementsPerChunk)); */
/* read repeatedly
*/
ElementsLeft = dwN;
while (ElementsLeft > 0L) {
ElementsToRead = min (ElementsPerChunk, ElementsLeft);
/* DBMSG((" ElementsToRead=%lu\n",ElementsToRead)); */
if (err = GtData (pDloc, order, pos, (WORD)ElementsToRead,
dtype, lpOut)) {
DBMSG(("GtHugeData: GtData\n"));
goto cu;
}
lpOut += ElementsToRead * tsize;
ElementsLeft -= ElementsToRead;
/* DBMSG((" ElementsLeft=%lu\n",ElementsLeft)); */
}
/* DBMSG(("GtHugeData: bottom\n")); */
cu: return err;
}
/* get TIFF 8-byte header
* currently only probably portable. depends somewhat on compiler's
* structure organization.
*/
RC GtTiffHdr (pDloc, pHdr)
PDLOC pDloc;
register TIFFHDR *pHdr;
{
RC err;
/* get the first word -- the byte order.
* first, set dlOrder to either valid value, since we will immediately
* change it. sort of a chicken and egg situation.
*/
/* pDloc->dlOrder = INTELTIFF; */
if (err = GtData (pDloc, INTELTIFF, (DWORD) 0, 1, TIFFSHORT,
(LPSTR)&pHdr->thByteOrder)) {
DBMSG(("GtTiffHdr: A\n"));
return err;
}
/* *pOrder = pHdr->thByteOrder; */
/* get the version
*/
if (err = GtData (pDloc, pHdr->thByteOrder, (DWORD) 2, 1, TIFFSHORT,
(LPSTR)&pHdr->thVersion)) {
DBMSG(("GtTiffHdr: AA\n"));
return err;
}
/* get the double word (IFD offset)
*/
if (err = GtData (pDloc, pHdr->thByteOrder, (DWORD)4, 1, TIFFLONG,
(LPSTR)&pHdr->thIfdOffset)) {
DBMSG(("GtTiffHdr: B\n"));
return err;
}
#if 0
DBMSG(("GtTiffHdr: ByteOrder=%x Version=%u IfdOffset=%lu\n",
pHdr->thByteOrder, pHdr->thVersion, pHdr->thIfdOffset));
#endif /* 0 */
/* return
*/
return SUCCESS;
}
/* get TIFF directory entry
*/
RC GtTiffEntry (pDloc, order, EntryOffset, pDe)
PDLOC pDloc;
WORD order;
DWORD EntryOffset;
register DIRENTRY *pDe;
{
RC err;
DWORD BytesToRead;
WORD tsize;
WORD wTmp;
/* get the 2 words beginning with deTag
*/
if (err = GtData (pDloc, order, EntryOffset, 2, TIFFSHORT,
(LPSTR)&pDe->deTag)) {
DBMSG(("GtTiffEntry: A\n"));
return err;
}
/* get the 2 dwords, beginning with deLength
*/
if (err = GtData (pDloc, order, EntryOffset + 4L, 2, TIFFLONG,
(LPSTR)&pDe->deLength)) {
DBMSG(("GtTiffEntry: B\n"));
return err;
}
/* fix up deVal, if it's not really a LONG
*/
#ifdef WINDOWS
if (order == MOTOROLATIFF) {
#endif
#ifdef MACINTOSH
if (order == INTELTIFF) {
#endif
if (err = GtTiffSizeof (pDe->deType, &tsize)) {
DBMSG(("GtTiffEntry: GtTiffSizeof\n"));
WARN ((HWND)NULL, IM_WARNING, IM_BAD_TTYPE);
return err;
}
BytesToRead = (DWORD)tsize * pDe->deLength;
if (BytesToRead <= 4) {
if (tsize == 2) { /* swap words */
wTmp = * (WORD *) &pDe->deVal;
* (WORD *) &pDe->deVal = * ((WORD *) &pDe->deVal + 1);
* ((WORD *) &pDe->deVal + 1) = wTmp;
}
else if (tsize == 1) { /* swap bytes */
swaw ((LPSTR)&pDe->deVal, (LPSTR)&pDe->deVal, 4);
}
}
}
/* return
*/
return SUCCESS;
}
/* Fill a Tiff Field structure
* Note: the caller should probably not totally die upon getting an error.
* Private data types are possible, for one thing. Just don't set the
* existence flag for the field.
*/
RC FillTField ARGS((PDLOC,WORD,DIRENTRY *,DWORD,TFIELD *));
LOCAL RC FillTField (pDloc, order, pDe, EntryOffset, pTF)
PDLOC pDloc;
WORD order;
register DIRENTRY *pDe;
DWORD EntryOffset;
register TFIELD *pTF;
{
RC err = SUCCESS;
HANDLE h;
LPSTR lp;
WORD TypeSize;
DWORD BytesToRead;
/* copy tag, type, and length from DIRENTRY structure
*/
pTF->Texists = TRUE;
pTF->Ttag = pDe->deTag;
pTF->Ttype = pDe->deType;
pTF->Tlength = pDe->deLength;
/* record the offset, for possible later modify-in-place action
*/
pTF->Tentryoffset = EntryOffset;
/* calculate needed space
*/
if (err = GtTiffSizeof (pTF->Ttype, &TypeSize)) {
DBMSG(("FillTField: unknown type\n"));
goto cu0;
}
BytesToRead = (DWORD)TypeSize * pTF->Tlength;
/* if <= 4 bytes, we're almost done. else we have to do some
* work.
*/
pTF->Talloc = FALSE; /* just to be safe */
if (BytesToRead <= 4) {
pTF->val.Tdword = pDe->deVal;
}
else {
/* allocate and lock a buffer
*/
if (!(h = MMAlloc (BytesToRead))) {
DBMSG(("FillTField: h\n"));
err = IM_MEM_FULL;
goto cu0;
}
if (!(lp = MMLock (h))) {
DBMSG(("FillTField: lp\n"));
err = IM_MEM_FAIL;
MMFree (h);
goto cu0;
}
/* read the data
*/
if (err = GtHugeData (pDloc, order, pDe->deVal, pDe->deLength,
pDe->deType, lp)) {
DBMSG(("FillTField: GtHugeData\n"));
MMUnlock (h);
MMFree (h);
goto cu0;
}
/* make sure that the val union contains the first N values from
* the memory buffer, so that we can use things like p->iBitsPerSample
* constructs even if there are 3 BitsPerSample values.
*/
lmemcpy ((LPSTR) &pTF->val.Tchar[0], lp, 4);
/* unlock the buffer
*/
MMUnlock (h);
/* stuff the handle into the TFIELD structure
*/
pTF->Thandle = h;
pTF->Talloc = TRUE;
} /* end of greater-than-4-byte case */
/* return
*/
cu0: return err;
}
RC TypeConvert ARGS((TFIELD *, WORD));
LOCAL RC TypeConvert (pTF, totype)
register TFIELD *pTF;
WORD totype; /* TIFFBYTE, etc */
{
RC err = SUCCESS;
WORD fromtype;
DWORD dwLength;
WORD SrcSize;
DWORD SrcBytes;
DWORD SrcVal;
LPSTR lpSrc;
WORD DstSize;
DWORD DstBytes;
DWORD DstVal;
LPSTR lpDst;
HANDLE hDst = (HANDLE)NULL;
/* DBMSG(("TypeConvert: top\n")); */
/* shorthands:
*/
fromtype = pTF->Ttype;
dwLength = pTF->Tlength;
/* DBMSG(("tfield:\n"));
* DBMSG((" Talloc=%u Ttag=%u Ttype=%u Tlength=%lu val=%lx\n",
* pTF->Talloc,pTF->Ttag,pTF->Ttype,pTF->Tlength,pTF->val.Tdword));
*/
/* if the same type, do nothing
*/
if (totype == fromtype) {
goto done;
}
/* calculate number of source bytes
*/
if (err = GtTiffSizeof (fromtype, &SrcSize)) {
DBMSG(("TypeConvert: bad dtype src\n"));
goto done;
}
SrcBytes = (DWORD)SrcSize * dwLength;
/* point to source data
*/
if (SrcBytes <= (DWORD)4) {
if (pTF->Talloc) {
DBMSG(("TypeConvert: size error A\n"));
err = IM_BUG; /* programming error */
goto done;
}
SrcVal = pTF->val.Tdword;
lpSrc = (LPSTR)&SrcVal;
} else {
if (!pTF->Talloc) {
DBMSG(("TypeConvert: size error B\n"));
err = IM_BUG; /* programming error */
goto done;
}
if (pTF->Thandle == (HANDLE)NULL) {
DBMSG(("TypeConvert: null handle\n"));
err = IM_BUG; /* programming error */
goto done;
}
if ((lpSrc = MMLock (pTF->Thandle)) == (LPSTR)NULL) {
DBMSG(("TypeConvert: Thandle\n"));
err = IM_MEM_FAIL;
goto done;
}
}
/* calculate number of destination bytes
*
* In the case of ASCII source and integer or
* floating point destination, we are going to
* allocate too much space, and quite possibly
* allocate when the result would fit into 4
* bytes, so make sure we take that into consideration
* below.
*/
if (err = GtTiffSizeof (totype, &DstSize)) {
DBMSG(("TypeConvert: bad dtype dst\n"));
if (pTF->Talloc) MMUnlock (pTF->Thandle);
goto done;
}
DstBytes = (DWORD)DstSize * dwLength;
/* point to destination data
*/
if (DstBytes <= (DWORD)4)
lpDst = (LPSTR)&DstVal;
else {
if (err = GetItLockIt (DstBytes, &hDst,
(LPBYTE *)&lpDst)) {
DBMSG(("TypeConvert: hDst\n"));
if (pTF->Talloc) MMUnlock (pTF->Thandle);
goto done;
}
}
/* convert depending on source and destination type
*/
{
/* if TIFFRATIONAL, convert to floating point or
* integer. Note that I am relaxing the definition
* of RATIONAL to include negative numbers.
*/
if (fromtype == TIFFRATIONAL &&
(totype == TIFFFLOAT || totype == TIFFSIGNED ||
totype == TIFFSHORT)) {
register long FAR *lpSrcPtr; /* assumption: long & DWORD are same length */
register LPSTR lpDstPtr;
register DWORD dwCnt;
float FloatVal;
short ShortVal;
/* set up
*/
lpSrcPtr = (long FAR *)lpSrc;
lpDstPtr = lpDst;
/* for each rational...
*/
for (dwCnt = (DWORD)0; dwCnt < dwLength; dwCnt++) {
/* calculate a float equivalent
*/
if (*(lpSrcPtr +1) == (DWORD)0) {
FloatVal = (float)0.0;
} else {
FloatVal = (float)*lpSrcPtr / (float)*(lpSrcPtr+1);
}
/* translate if necessary, and store
* into the destination array
*/
if (totype == TIFFFLOAT) {
*((float FAR *)lpDstPtr) = FloatVal;
} else {
if (FloatVal >= (float)0.0) {
ShortVal = (short)(FloatVal + .5);
} else {
/* is this right? */
ShortVal = (short)(FloatVal - .5);
}
}
if (totype == TIFFSHORT) {
*((LPWORD)lpDstPtr) = (WORD)ShortVal;
} else if (totype == TIFFSIGNED) {
*((short FAR *)lpDstPtr) = ShortVal;
}
/* increment the pointers
*/
lpSrcPtr++;
lpDstPtr += DstSize;
}
/* make sure that the val section contains the first N values from
* the destination array
*/
if (DstBytes > (DWORD)4) {
lmemcpy ((LPSTR) &pTF->val.Tdword, (LPSTR)lpDst, 4);
}
/* set the new type
*/
pTF->Ttype = totype;
} /* end of rational to float/short/WORD section */
/* else if an unsigned integer (TIFFBYTE, TIFFSHORT, or TIFFLONG),
* do the appropriate conversion. I probably should check for
* problems when converting to something smaller. TODO.
*/
else if ((fromtype == TIFFBYTE || fromtype == TIFFSHORT ||
fromtype == TIFFLONG) &&
(totype == TIFFBYTE || totype == TIFFSHORT ||
totype == TIFFLONG)) {
register LPSTR lpSrcPtr = lpSrc;
register LPSTR lpDstPtr = lpDst;
register DWORD dwCnt;
register WORD TiffShort;
register DWORD TiffLong;
if (fromtype == TIFFBYTE && totype == TIFFSHORT) {
for (dwCnt = (DWORD)0; dwCnt < dwLength; dwCnt++) {
*((LPWORD)lpDstPtr) = (WORD)*((LPBYTE)lpSrcPtr);
lpSrcPtr += SrcSize;
lpDstPtr += DstSize;
}
} else if (fromtype == TIFFBYTE && totype == TIFFLONG) {
for (dwCnt = (DWORD)0; dwCnt < dwLength; dwCnt++) {
*((LPDWORD)lpDstPtr) = (DWORD)*((LPBYTE)lpSrcPtr);
lpSrcPtr += SrcSize;
lpDstPtr += DstSize;
}
} else if (fromtype == TIFFSHORT && totype == TIFFBYTE) {
for (dwCnt = (DWORD)0; dwCnt < dwLength; dwCnt++) {
TiffShort = *((LPWORD)lpSrcPtr);
if (TiffShort > MAXBYTE) {
TiffShort = MAXBYTE;
}
*((LPBYTE)lpDstPtr) = (BYTE)TiffShort;
lpSrcPtr += SrcSize;
lpDstPtr += DstSize;
}
} else if (fromtype == TIFFSHORT && totype == TIFFLONG) {
for (dwCnt = (DWORD)0; dwCnt < dwLength; dwCnt++) {
*((LPDWORD)lpDstPtr) = (DWORD)*((LPWORD)lpSrcPtr);
lpSrcPtr += SrcSize;
lpDstPtr += DstSize;
}
} else if (fromtype == TIFFLONG && totype == TIFFBYTE) {
for (dwCnt = (DWORD)0; dwCnt < dwLength; dwCnt++) {
TiffLong = *((LPDWORD)lpSrcPtr);
if (TiffLong > MAXWORD) {
TiffLong = MAXWORD;
}
*((LPBYTE)lpDstPtr) = (BYTE)TiffLong;
lpSrcPtr += SrcSize;
lpDstPtr += DstSize;
}
} else if (fromtype == TIFFLONG && totype == TIFFSHORT) {
for (dwCnt = (DWORD)0; dwCnt < dwLength; dwCnt++) {
TiffLong = *((LPDWORD)lpSrcPtr);
if (TiffLong > MAXWORD) {
TiffLong = MAXWORD;
}
*((LPWORD)lpDstPtr) = (WORD)TiffLong;
lpSrcPtr += SrcSize;
lpDstPtr += DstSize;
}
}
/* make sure that the val section contains the first N values from
* the destination array, so that I can have a 3-valued BitsPerSample
* (forced to be the same) but still get "the" BitsPerSample value
* by using the p->iBitsPerSample contruct
*/
if (DstBytes > (DWORD)4) {
lmemcpy ((LPSTR) &pTF->val.Tdword, (LPSTR)lpDst, 4);
}
/* set the new type
*/
pTF->Ttype = totype;
} /* end of unsigned section */
/* else if none of the above cases, give up.
*/
else {
DBMSG(("TypeConvert: type problem. fromtype=%d totype=%d\n",
fromtype, totype));
if (pTF->Talloc) MMUnlock (pTF->Thandle);
if (hDst) {
UnlockItFreeIt (hDst);
hDst = (HANDLE) NULL;
}
err = IM_BUG; /* programming error */
goto done;
}
} /* end of conversion section */
/* if neither the source nor destination is allocated,
* just copy into the 4-byte value
*/
if (!pTF->Talloc && !hDst) {
pTF->val.Tdword = DstVal;
}
/* else if source and destination are both allocated,
* free the old buffer, and store the new destination handle
*/
else if (pTF->Talloc && hDst) {
UnlockItFreeIt (pTF->Thandle);
pTF->Thandle = hDst;
MMUnlock (hDst);
}
/* else if destination is allocated, but not the source,
* just store the new destination handle
*/
else if (!pTF->Talloc && hDst) {
pTF->Thandle = hDst;
MMUnlock (pTF->Thandle);
pTF->Talloc = TRUE;
}
/* else if source is allocated, but not the destination,
* unlock and free the buffer, and copy the value.
*/
else if (pTF->Talloc && !hDst) {
UnlockItFreeIt (pTF->Thandle);
pTF->Talloc = FALSE;
pTF->val.Tdword = DstVal;
}
/* return
*/
done: return err;
}
/* check for bad values, convert from one format to another
* if necessary, and store the information in the appropriate
* TFIELD structure in the IMAG structure
*/
RC NicefyTField ARGS((TFIELD *, IMAG *));
RC NicefyTField (pTF, x)
register TFIELD *pTF;
register IMAG *x;
{
RC err = SUCCESS;
register WORD Tag;
Tag = pTF->Ttag;
/* DBMSG(("Nicefy: unsigned tag=%u signed tag=%d\n",
* pTF->Ttag, pTF->Ttag));
*/
if (Tag == TGNEWSUBFILETYPE) {
if (err = TypeConvert (pTF, TIFFLONG))
goto cu0;
pTF->Texists = TRUE;
x->tf[X_NEWSUBFILETYPE] = *pTF; /* structure copy */
} else if (Tag == TGIMAGEWIDTH) {
if (err = TypeConvert (pTF, TIFFSHORT))
goto cu0;
pTF->Texists = TRUE;
x->tf[X_IMAGEWIDTH] = *pTF; /* structure copy */
} else if (Tag == TGIMAGELENGTH) {
if (err = TypeConvert (pTF, TIFFSHORT))
goto cu0;
pTF->Texists = TRUE;
x->tf[X_IMAGELENGTH] = *pTF; /* structure copy */
} else if (Tag == TGBITSPERSAMPLE) {
if (err = TypeConvert (pTF, TIFFSHORT))
goto cu0;
pTF->Texists = TRUE;
x->tf[X_BITSPERSAMPLE] = *pTF; /* structure copy */
} else if (Tag == TGCOMPRESSION) {
if (err = TypeConvert (pTF, TIFFSHORT))
goto cu0;
pTF->Texists = TRUE;
x->tf[X_COMPRESSION] = *pTF; /* structure copy */
} else if (Tag == TGPHOTOMETRICINTERPRETATION) {
if (err = TypeConvert (pTF, TIFFSHORT))
goto cu0;
pTF->Texists = TRUE;
x->tf[X_PHOTOMETRICINTERP] = *pTF; /* structure copy */
} else if (Tag == TGSTRIPOFFSETS) {
if (err = TypeConvert (pTF, TIFFLONG))
goto cu0;
pTF->Texists = TRUE;
x->tf[X_STRIPOFFSETS] = *pTF; /* structure copy */
} else if (Tag == TGSAMPLESPERPIXEL) {
if (err = TypeConvert (pTF, TIFFSHORT))
goto cu0;
pTF->Texists = TRUE;
x->tf[X_SAMPLES] = *pTF; /* structure copy */
} else if (Tag == TGSTRIPBYTECOUNTS) {
if (err = TypeConvert (pTF, TIFFLONG))
goto cu0;
pTF->Texists = TRUE;
x->tf[X_STRIPBYTECOUNTS] = *pTF; /* structure copy */
} else if (Tag == TGROWSPERSTRIP) {
if (err = TypeConvert (pTF, TIFFSHORT))
goto cu0;
pTF->Texists = TRUE;
x->tf[X_ROWSPERSTRIP] = *pTF; /* structure copy */
} else if (Tag == TGXRESOLUTION) {
if (err = TypeConvert (pTF, TIFFFLOAT))
goto cu0;
pTF->Texists = TRUE;
x->tf[X_XRESOLUTION] = *pTF; /* structure copy */
if (x->fXResolution == (float)0.0)
x->fXResolution = (float)300.0;
} else if (Tag == TGYRESOLUTION) {
if (err = TypeConvert (pTF, TIFFFLOAT))
goto cu0;
pTF->Texists = TRUE;
x->tf[X_YRESOLUTION] = *pTF; /* structure copy */
if (x->fYResolution == (float)0.0)
x->fYResolution = (float)300.0;
} else if (Tag == TGPLANARCONFIGURATION) {
if (err = TypeConvert (pTF, TIFFSHORT))
goto cu0;
#if 0
pTF->Texists = TRUE;
x->tf[X_PLANAR] = *pTF; /* structure copy */
#endif
} else if (Tag == TGGRAYUNIT) {
if (err = TypeConvert (pTF, TIFFSHORT))
goto cu0;
pTF->Texists = TRUE;
x->tf[X_GRAYUNIT] = *pTF; /* structure copy */
} else if (Tag == TGGRAYCURVE) {
if (err = TypeConvert (pTF, TIFFSHORT))
goto cu0;
pTF->Texists = TRUE;
x->tf[X_GRAYCURVE] = *pTF; /* structure copy */
} else if (Tag == TGRESOLUTIONUNIT) {
if (err = TypeConvert (pTF, TIFFSHORT))
goto cu0;
pTF->Texists = TRUE;
x->tf[X_RESOLUTIONUNIT] = *pTF; /* structure copy */
} else if (Tag == TGPREDICTOR) {
if (err = TypeConvert (pTF, TIFFSHORT))
goto cu0;
pTF->Texists = TRUE;
x->tf[X_PREDICTOR] = *pTF; /* structure copy */
} else {
/* DBMSG(("GtTiffInfo: unrecognized tag %d\n",de.deTag)); */
/*
* no big deal, probably.
*/
}
cu0: return err;
}
/************************ exported procedures **********************/
/* read all the TIFF fields that we care about.
* if from file, it should be open for read.
* currently, subsequent IFD's are ignored.
*
* make sure you fill out the DLOC structure before calling this routine.
*/
RC GtTiffInfo (pDloc, x)
PDLOC pDloc; /* table/file input structure */
register IMAG *x; /* this is where the field information will be put */
{
RC err = SUCCESS;
TIFFHDR th;
DIRENTRY de;
TFIELD tf;
WORD IfdEntries;
DWORD NextIfd;
DWORD EntryOffset;
WORD ii;
DWORD location;
/* DBMSG(("GtTiffInfo: top\n")); */
/* initialize the structure
*/
InitImag (x);
/* get the 8-byte header
*/
if (err = GtTiffHdr (pDloc, &th)) {
DBMSG(("GtTiffInfo(): can't read header.\n"));
goto cu0;
}
x->iFileType = th.thByteOrder;
/* pDloc->dlOrder = th.thByteOrder; */
/* check version
*/
if (th.thVersion != VERSION42) {
DBMSG(("GtTiffInfo: wrong version\n"));
err = IM_BUG; /* should have been caught earlier */
goto cu0;
}
x->iVersion = th.thVersion;
/* read the number of directory entries
*/
if (err = GtData (pDloc, th.thByteOrder, th.thIfdOffset, 1, TIFFSHORT,
(LPSTR)&IfdEntries)) {
DBMSG(("GtTiffInfo: can't read # of dir entries\n"));
goto cu0;
}
/* loop through the entries
*/
EntryOffset = th.thIfdOffset + sizeof(IfdEntries);
for (ii = 0; ii < IfdEntries; ii++, EntryOffset += sizeof(de)) {
/* read the entry
*/
if (err = GtTiffEntry (pDloc, th.thByteOrder, EntryOffset, &de)) {
DBMSG(("GtTiffInfo: can't read entry.\n"));
err = SUCCESS;
continue;
}
/* convert to a TFIELD structure, reading big fields as necessary
*/
if (err = FillTField (pDloc, th.thByteOrder, &de, EntryOffset, &tf)) {
DBMSG(("GtTiffInfo: FillTField\n"));
err = SUCCESS;
continue;
}
/* check for bad values, convert from one format to another
* if necessary, and store the information in the appropriate
* TFIELD structure in the IMAG structure
*/
if (err = NicefyTField (&tf, x)) {
DBMSG(("GtTiffInfo: NicefyTField\n"));
err = SUCCESS;
continue;
}
} /* end of direntry loop */
/* check the offset of the next IFD
*/
{
DWORD NextIFD;
WORD Dummy;
if (err = GtData (pDloc, th.thByteOrder, EntryOffset, 1, TIFFLONG,
(LPSTR)&NextIFD)) {
DBMSG(("GtTiffInfo: can't read next-IFD-offset\n"));
err = IM_BAD_NEXT_IFD;
goto cu0;
}
if (err = GtData (pDloc, th.thByteOrder, NextIFD, 1, TIFFSHORT,
(LPSTR)&Dummy)) {
DBMSG(("GtTiffInfo: can't read next IFD\n"));
err = IM_BAD_NEXT_IFD;
goto cu0;
}
}
/* miscellaneous correctness checks
*/
if (err = CheckTiff (x)) {
/* DBMSG((" CheckTiff\n")); */
goto cu0;
}
/* return
*/
cu0: return err;
}